package com.sk.commonadapter_android.adapter;

import android.content.Context;
import android.content.pm.PackageManager;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.View;

import com.sk.commonadapter_android.adapter.refresh.BaseRefreshImp;
import com.sk.commonadapter_android.adapter.refresh.LoadMoreLayout;
import com.sk.commonadapter_android.adapter.refresh.RefreshHeaderLayout;

/**
 * @Author yemao
 * @Email yrmao9893@163.com
 * @Date 2017/6/13
 * @Des 上拉加载下拉刷新的RecyclerView!
 */

public class RefreshRecyclerView extends RecyclerView {
    private RecyclerViewWrapAdapter mWrapAdapter;
    private SparseArray<View> mHeaderViews;
    private SparseArray<View> mFooterViews;
    private PullLinstener mPullLinstener;
    private RefreshHeaderLayout mRefreshHeaderLayout;

    private boolean pullRefreshEnabled = true;
    private boolean loadingMoerEnabled = true;
    private boolean isLoadingData = false;
    private boolean istOtherFooterView = false;
    private boolean hasLoadMareData = true;
    private int previousTotal = 0;
    private float mLastY = -1;
    private static final float DRAG_RATE = 1.75f;

    public RefreshRecyclerView(Context context) {
        this(context, null);
    }

    public RefreshRecyclerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RefreshRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        mHeaderViews = new SparseArray<>();
        mFooterViews = new SparseArray<>();
        if (pullRefreshEnabled) {
            mRefreshHeaderLayout = new RefreshHeaderLayout(context);
            addHeaderView(mRefreshHeaderLayout);
        }

        //初始化上拉加载
        LoadMoreLayout footView = new LoadMoreLayout(getContext());
        addFooterView(footView, false);
    }

    /**
     * 添加其他的footerView后上拉加载就会禁用掉
     *
     * @param istOtherFooterView 是不是其他的footerview
     * @param view
     */
    public void addFooterView(View view, boolean istOtherFooterView) {
        int position = mFooterViews.size();
        if (!istOtherFooterView) {
            //如果是加载的foot先清空已存在的view
            mFooterViews.clear();
            mFooterViews.put(0, view);
        } else {
            mFooterViews.put(position, view);
        }
        this.istOtherFooterView = istOtherFooterView;
    }

    public void addHeaderView(View view) {
        int position = mHeaderViews.size();
        mHeaderViews.put(position, view);
    }

    @Override
    public void onScrollStateChanged(int state) {
        super.onScrollStateChanged(state);
        if (state == RecyclerView.SCROLL_STATE_IDLE
                && mPullLinstener != null
                && loadingMoerEnabled
                && !isLoadingData
                && !mRefreshHeaderLayout.releaseAction()
                ) {

            int lastVisibleItemPosition = 0;
            LayoutManager mLayoutManager = getLayoutManager();

            if (mLayoutManager instanceof GridLayoutManager) {
                lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
            } else if (mLayoutManager instanceof StaggeredGridLayoutManager) {
                int[] into = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()];
                ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(into);
                lastVisibleItemPosition = findMax(into);
            } else if (mLayoutManager instanceof LinearLayoutManager) {
                lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
            }

            if (mLayoutManager.getChildCount() > 0
                    && lastVisibleItemPosition >= mLayoutManager.getItemCount() - 1
                    && mLayoutManager.getItemCount() >= mLayoutManager.getChildCount()
                    && hasLoadMareData) {
                isLoadingData = true;
                View footView = mFooterViews.get(0);
                if (footView instanceof LoadMoreLayout) {
                    ((LoadMoreLayout) footView).setState(LoadMoreLayout.STATE_LOADING);
                    mPullLinstener.onLoadMore();
                }
            }


        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLastY = e.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                float deltaY = e.getRawY() - mLastY;
                mLastY = e.getRawY();
                if (isOnTop() && pullRefreshEnabled) {
                    mRefreshHeaderLayout.onMove(deltaY / DRAG_RATE);
                    if (mRefreshHeaderLayout.getVisiableHeight() > 0
                            && mRefreshHeaderLayout.getState() < BaseRefreshImp.STATE_REFRESHING) {
                        return false;
                    }
                }
                break;
            default:
                mLastY = -1;
                if (isOnTop() && pullRefreshEnabled) {
                    if (mRefreshHeaderLayout.releaseAction()) {
                        if (mPullLinstener != null) {
                            mPullLinstener.onRefresh();
                            previousTotal = 0;
                            hasLoadMareData = true;

                        }
                    }
                }
        }
        return super.onTouchEvent(e);

    }
    public void setPullRefreshEnabled(boolean pullRefreshEnabled){
        this.pullRefreshEnabled=pullRefreshEnabled;
//        View headerView= mHeaderViews.get(0);
//        if (headerView==null)
//            return;
//
//        if (pullRefreshEnabled){
//            if (headerView instanceof RefreshHeaderLayout){
//                headerView.setVisibility(VISIBLE);
//            }
//        }else {
//            if (headerView instanceof RefreshHeaderLayout){
//                headerView.setVisibility(GONE);
//            }
//        }

    }
    public void setLoadMoerEnabled(boolean loadingMoerEnabled) {
        this.loadingMoerEnabled = loadingMoerEnabled;
        if (loadingMoerEnabled) {
            if (mFooterViews != null) {
                LoadMoreLayout footView = new LoadMoreLayout(getContext());
                addFooterView(footView, false);
            }
        } else {
            if (mFooterViews != null) {
                mFooterViews.remove(0);
            }
        }
    }

    public void setPullLinstener(PullLinstener mPullLinstener) {
        this.mPullLinstener = mPullLinstener;
    }


    private boolean isOnTop() {
        if (mHeaderViews == null)
            return false;
        if (mHeaderViews.size() == 0)
            return false;
        View view = mHeaderViews.get(0);
        if (view.getParent() != null)
            return true;
        else
            return false;
    }

    public void onRefreshComlete() {
        if (!isLoadingData)
            mRefreshHeaderLayout.refreshComplate();
        else
            onLoadMoreComlete();
    }

    public void onLoadMoreComlete() {
        isLoadingData = false;
        View footView = mFooterViews.get(0);
        if (previousTotal < getLayoutManager().getItemCount()) {
            if (footView instanceof LoadMoreLayout) {
                ((LoadMoreLayout) footView).setState(LoadMoreLayout.STATE_COMPLETE);
            }
        } else {
            if (footView instanceof LoadMoreLayout) {
                ((LoadMoreLayout) footView).setState(LoadMoreLayout.STATE_NOMORE);
            }
            hasLoadMareData = false;
        }
        previousTotal = getLayoutManager().getItemCount();
    }

    public void onNoMoreLoad() {
        isLoadingData = false;
        View footView = mFooterViews.get(0);
        if (footView instanceof LoadMoreLayout) {
            ((LoadMoreLayout) footView).setState(LoadMoreLayout.STATE_NOMORE);
        }
        hasLoadMareData = false;
    }

    private int findMax(int[] lastPositions) {
        int max = lastPositions[0];
        for (int value : lastPositions) {
            if (value > max) {
                max = value;
            }
        }
        return max;
    }

    @Override
    public void setAdapter(Adapter adapter) {
        mWrapAdapter = new RecyclerViewWrapAdapter(adapter, mHeaderViews, mFooterViews);
        super.setAdapter(mWrapAdapter);
        adapter.registerAdapterDataObserver(mDataObserver);
    }

    private final RecyclerView.AdapterDataObserver mDataObserver = new AdapterDataObserver() {
        @Override
        public void onChanged() {
            super.onChanged();
            mWrapAdapter.notifyDataSetChanged();
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount) {
            super.onItemRangeChanged(positionStart, itemCount);
            mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount);
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
            super.onItemRangeChanged(positionStart, itemCount, payload);
            mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount, payload);
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            super.onItemRangeInserted(positionStart, itemCount);
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            super.onItemRangeRemoved(positionStart, itemCount);
            mWrapAdapter.notifyItemRangeRemoved(positionStart, itemCount);
        }

        @Override
        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            super.onItemRangeMoved(fromPosition, toPosition, itemCount);
            mWrapAdapter.notifyItemMoved(fromPosition, toPosition);
        }
    };

    public interface PullLinstener {
        void onRefresh();

        void onLoadMore();

    }
}
